package com.financial.business.balance.service.gy.impl;

import com.financial.business.balance.config.GYAccessTokenConfig;
import com.financial.business.balance.config.UrlConfig;
import com.financial.business.balance.connector.SysconfigFeign;
import com.financial.business.balance.constants.FinancialRefundBalanceEnumConstants;
import com.financial.business.balance.dao.FinancialGYRefundBalanceDao;
import com.financial.business.balance.domain.FinancialGYRefundBalanceDO;
import com.financial.business.balance.dto.FinancialGYBalanceRefundDTO;
import com.financial.business.balance.service.gy.FinancialGYBalanceRefundService;
import com.financial.business.balance.utils.*;
import com.financial.business.balance.utils.apiresult.ApiResult;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Davidbieber
 * @description 余额退款业务接口实现类
 * @email davidbieber@163.com
 * @date 2019/12/6 4:21 PM
 */
@Service
public class FinancialGYBalanceRefundServiceImpl implements FinancialGYBalanceRefundService {

    protected static final Logger logger = LoggerFactory.getLogger(FinancialGYBalanceRefundServiceImpl.class);

    @Autowired
    private SysconfigFeign sysconfigFeign;

    @Autowired
    private GYAccessTokenConfig gyAccessTokenConfig;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private FinancialGYRefundBalanceDao financialGYRefundBalanceDao;

    @Autowired
    private HttpClientUtils httpClientUtils;

    @Override
    public ApiResult refund(String requestParam) {
        logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----获取够样支付退款类型为：" + requestParam);
        FinancialGYBalanceRefundDTO financialGYRefundDTO = JsonUtils.convertBean(requestParam, FinancialGYBalanceRefundDTO.class);
        Map<String, Object> params = JsonUtils.jsonToMap(requestParam);
        /*退款金额*/
        Object tempParam = params.get("total_amount");
        String totalAmountStr = tempParam == null ? null : tempParam.toString();
        /*对接平台商户号*/
        tempParam = params.get("store_no");
        String storeNo = tempParam == null ? null : tempParam.toString();
        /*退款交易单号*/
        tempParam = params.get("out_trade_no");
        String outTradeNo = tempParam == null ? null : tempParam.toString();
        /*对接平台退款单号*/
        tempParam = params.get("refund_no");
        String refundNo = tempParam == null ? null : tempParam.toString();
        /*对接平台标识*/
        tempParam = params.get("platform_no");
        String platformNo = tempParam == null ? null : tempParam.toString();
        /*用户ID*/
        tempParam = params.get("customer_id");
        String customerId = tempParam == null ? null : tempParam.toString();
        /*现在支付渠道类型编码*/
        tempParam = params.get("pay_channel_no");
        String payChannelNo = tempParam == null ? null : tempParam.toString();
        /*退款类型*/
        tempParam = params.get("refund_type");
        String refundType = tempParam == null ? null : tempParam.toString();
        /*退款原因*/
        tempParam = params.get("refund_reason");
        String refundReason = tempParam == null ? null : tempParam.toString();
        /*余额退款异步回调地址*/
        tempParam = params.get("notify_url");
        String notifyUrl = tempParam == null ? null : tempParam.toString();
        if (StringUtils.isBlank(totalAmountStr) || StringUtils.isBlank(storeNo)
                || StringUtils.isBlank(outTradeNo) || StringUtils.isBlank(refundNo)
                || StringUtils.isBlank(platformNo) || StringUtils.isBlank(customerId)
                || StringUtils.isBlank(refundReason) || StringUtils.isBlank(payChannelNo)
                || StringUtils.isBlank(refundType)) {
            /*对所传字段进行非空校验判断*/
            logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----余额退款请求检测到的非空字段为:" + ValidateUtils.validateProperty(financialGYRefundDTO));
            return ApiResult.failure(ValidateUtils.validateProperty(financialGYRefundDTO));
        }
        try {
            /*获取够样支付平台信息*/
            ApiResult apiResult = sysconfigFeign.platfromInfo(payChannelNo);
            String apiResultMsg = (String) apiResult.getResult();
            if (apiResult.getCode() == FinancialRefundBalanceEnumConstants.ENUM_CODE_SUC || (apiResultMsg != null && apiResultMsg != "")) {
                /*获取每个参数信息*/
                Map<String, Object> map = JsonUtils.jsonToMap(apiResultMsg);
                String platfromNo = (String) map.get("platfrom_no");
                String platformName = (String) map.get("platform_name");
                String passWord = (String) map.get("pass_word");
                String secret = (String) map.get("secret");
                /*缓存中获取token*/
                String resultAccessToken;
                Object object = redisUtils.getValue("financialAccessToken");
                if (null == object) {
                    /*对参数进行验签加密*/
                    String sign = MD5Utils.md5(platformName + platfromNo + passWord + secret);
                    resultAccessToken = gyAccessTokenConfig.getGYAccessToken(platformName, passWord, secret, sign);
                } else {
                    resultAccessToken = (String) object;
                }
                /*对分账所有的金额进行精确度设置，保留两位小数*/
                /*支付总金额*/
                BigDecimal totalAmount = new BigDecimal(totalAmountStr).setScale(2, RoundingMode.HALF_UP);
                /*保存数据初始化*/
                FinancialGYRefundBalanceDO financialGYPayRefundDO = new FinancialGYRefundBalanceDO();
                /*通过订单号查询数据是否存在，决定保存或者更新*/
                FinancialGYRefundBalanceDO financialGYRefundBalanceDOInfo = financialGYRefundBalanceDao.getOne(outTradeNo);
                logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----余额退款订单号:{},是否存在:{}", outTradeNo, financialGYRefundBalanceDOInfo);
                int res = 0;
                if (financialGYRefundBalanceDOInfo != null) {
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----通过订单号查库数据存在,执行更新操作");
                    Map<String, Object> dataParams = new HashMap<>();
                    dataParams.put("gmtModified", new Date());
                    dataParams.put("returnMessage", FinancialRefundBalanceEnumConstants.ENUM_STATE_FAIL);
                    dataParams.put("state", FinancialRefundBalanceEnumConstants.ENUM_STATE_WAIT);
                    dataParams.put("outTradeNo", outTradeNo);
                    /*调取订单status对订单状态进行判断*/
                    String state = financialGYRefundBalanceDOInfo.getState();
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----通过订单号查库数据状态,订单号:{},订单状态:{}", outTradeNo, state);
                    /*获取数据库已经有的退款金额*/
                    BigDecimal totalAmountData = financialGYRefundBalanceDOInfo.getTotalAmount();
                    if (totalAmountData.compareTo(totalAmount) != 0) {
                        return ApiResult.failure("余额退款金额校验失败！");
                    }
                    /*状态判断*/
                    if (state.equals("1")) {
                        logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----通过订单号查库数据状态为退款成功");
                        return ApiResult.success("该订单退款已成功!");
                    } else {
                        logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----通过订单号查库数据状态为退款失败或未调用");
                        res = financialGYRefundBalanceDao.updateInfo(dataParams);
                    }
                } else {
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----通过订单号查库数据不存在,执行保存操作");
                    financialGYPayRefundDO.setCustomerId(customerId);
                    financialGYPayRefundDO.setGmtCreate(new Date());
                    financialGYPayRefundDO.setOutTradeNo(outTradeNo);
                    financialGYPayRefundDO.setPlatformNo(platformNo);
                    financialGYPayRefundDO.setRefundNo(refundNo);
                    financialGYPayRefundDO.setResqContent(requestParam);
                    financialGYPayRefundDO.setReturnMessage(FinancialRefundBalanceEnumConstants.ENUM_RETURNMESSAGE_FAIL);
                    financialGYPayRefundDO.setState(FinancialRefundBalanceEnumConstants.ENUM_STATE_WAIT);
                    financialGYPayRefundDO.setStoreNo(storeNo);
                    financialGYPayRefundDO.setTotalAmount(totalAmount);
                    financialGYPayRefundDO.setIsDelete(FinancialRefundBalanceEnumConstants.ENUM_ISDELETE_UNDEL);
                    res = financialGYRefundBalanceDao.save(financialGYPayRefundDO);
                }
                if (res > 0) {
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----保存金融中心数据信息成功！");
                    /*拼接请求参数对接够样平台*/
                    Map<String, Object> requestMap = new HashMap<>();
                    requestMap.put("customerUuid", customerId);
                    requestMap.put("payMoney", totalAmountStr);
                    requestMap.put("prePayNo", outTradeNo);
                    requestMap.put("accessToken", resultAccessToken);
                    //余额平台回调地址
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----拼接退款请求参数对接够样平台:" + JsonUtils.objectToJson(requestMap));
                    String result = httpClientUtils.doPost(UrlConfig.BALANCE_GY_REFUND_URL, requestMap);
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----调用够样余额中心返回值为:" + result);
                    Map<String, Object> resultMap = JsonUtils.jsonToMap(result);
                    /*更改数据库状态*/
                    Map<String, Object> updateMap = new HashMap<>();
                    updateMap.put("outTradeNo", outTradeNo);
                    updateMap.put("gmtModified", new Date());
                    if (!FinancialRefundBalanceEnumConstants.ENUM_GYRETURNCODE_SUC.equals(resultMap.get("return_code"))) {
                        updateMap.put("state", FinancialRefundBalanceEnumConstants.ENUM_STATE_FAIL);
                        updateMap.put("returnMessage", result);
                        financialGYRefundBalanceDao.updateInfo(updateMap);
                        return ApiResult.failure(result);
                    }
                    updateMap.put("state", FinancialRefundBalanceEnumConstants.ENUM_STATE_SUC);
                    updateMap.put("returnMessage", result);
                    financialGYRefundBalanceDao.updateInfo(updateMap);
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----请求金融中心余额退款接口结果为:" + JsonUtils.jsonToMap(result));
                    /*返回信息给调用端*/
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----返回信息给调用端:" + result);
                    return ApiResult.success(result);
                } else {
                    logger.info("FinancialGYBalanceRefundServiceImpl.refund()-----保存金融中心数据信息失败！");
                    return ApiResult.failure(requestParam);

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("FinancialGYBalanceRefundServiceImpl.refund()-----金融中心数据信息失败:" + e.getMessage());
        }
        return ApiResult.failure(requestParam);
    }
}